/**
 * 
 */
package co.fitstart.entity.user.fit;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;

import com.demo2do.core.format.PersistentFormat;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import co.fitstart.entity.reference.Gender;
import co.fitstart.entity.user.investigation.FitInvestigation;


/**
 * 
 * @author mohanlan
 *
 */
@PersistentFormat
@JsonIgnoreProperties(value={"hibernate_lazy_initializer","handler","fieldHandler"})
public class UserFit {
    
    private Integer height;
    
    private Float weight;
    
    private Integer age;
    
    @Enumerated(EnumType.ORDINAL)
    private Gender gender;
    
    /** BMI 值 */
    private BigDecimal bmiValue;
    
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @PersistentFormat
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Shape shape;
    
    /** 最后更新时间 */
    private Date lastUpdateTime;
    
    /**
     * The default constructor
     */
    public UserFit() {
        
    }
    
    /**
     * Edit user shape
     * 
     * @param shape
     * @return
     */
    public UserFit editShape(Shape shape) {
        this.shape = shape;
        return this;
    }
    
    /**
     * @param height
     * @param weight
     * @param age
     * @param gender
     * @return
     */
    public UserFit editFit(Integer height, Float weight, Integer age, Gender gender) {
        this.height = height;
        this.weight = weight;
        this.age = age;
        this.gender = gender;
        
        this.calculateBmi();
        
        return this;
    }
    
    /**
     * 
     * @param userFit
     * @return
     */
    public UserFit editFit(UserFit userFit) {
        this.height = userFit.getHeight();
        this.weight = userFit.getWeight();
        this.gender = userFit.getGender();
        this.age = userFit.getAge();
        
        this.bmiValue = userFit.getBmiValue();
        
        return this;
    }
    
    /**
     * 
     * @return
     */
    public UserFit calculateBmi() {
        
        BigDecimal divisor = new BigDecimal(this.height).divide(new BigDecimal(100))
                   .multiply(new BigDecimal(this.height).divide(new BigDecimal(100)));
        
        this.bmiValue = new BigDecimal(this.weight).divide(divisor, 2, RoundingMode.CEILING);
        
        return this;
    }
    
    /**
     * @param shape
     * @param fitInvestigation
     * @return
     */
    public UserFit edit(Shape shape, FitInvestigation fitInvestigation) {
        this.shape = shape;
        this.height = fitInvestigation.getHeight();
        this.weight = fitInvestigation.getWeight();
        this.age = fitInvestigation.getAge();
        this.gender = fitInvestigation.getGender();
        this.lastUpdateTime = new Date();
        return this;
    }
    
    /**
     * 
     * @param gender
     * @return
     */
    public UserFit editGender(Gender gender) {
        this.gender = gender;
        return this;
    }
    
    /**
     * @return the height
     */
    public Integer getHeight() {
        return height;
    }

    /**
     * @return the weight
     */
    public Float getWeight() {
        return weight;
    }

    /**
     * @return the age
     */
    public Integer getAge() {
        return age;
    }

    /**
     * @return the sex
     */
    public Gender getGender() {
        return gender;
    }

    /**
     * @return the bmiValue
     */
    public BigDecimal getBmiValue() {
        return bmiValue;
    }

    /**
     * @return the shape
     */
    public Shape getShape() {
        return shape;
    }

    /**
     * @return the lastUpdateTime
     */
    public Date getLastUpdateTime() {
        return lastUpdateTime;
    }

    /**
     * @param height the height to set
     */
    public void setHeight(Integer height) {
        this.height = height;
    }

    /**
     * @param weight the weight to set
     */
    public void setWeight(Float weight) {
        this.weight = weight;
    }

    /**
     * @param age the age to set
     */
    public void setAge(Integer age) {
        this.age = age;
    }

    /**
     * @param gender the gender to set
     */
    public void setGender(Gender gender) {
        this.gender = gender;
    }

    /**
     * @param bmiValue the bmiValue to set
     */
    public void setBmiValue(BigDecimal bmiValue) {
        this.bmiValue = bmiValue;
    }

    /**
     * @param shape the shape to set
     */
    public void setShape(Shape shape) {
        this.shape = shape;
    }

    /**
     * @param lastUpdateTime the lastUpdateTime to set
     */
    public void setLastUpdateTime(Date lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }
}
